<template>
  <div class="video-call-container">
    <div class="video-container">
      <video ref="localVideo" class="video-element local" autoplay muted></video>
      <video ref="remoteVideo" class="video-element remote" autoplay muted playsinline></video>


      <!-- 各种状态的控制界面 -->
      <div v-if="callStatus === 'idle'" class="control-panel">
        <button @click="startCall" class="call-button">发起视频通话</button>
      </div>

      <div v-if="callStatus === 'calling'" class="control-panel">
        <p>等待对方接听...</p>
        <button @click="hangUp" class="hangup-button">挂断</button>
      </div>

      <div v-if="callStatus === 'ringing'" class="control-panel">
        <p>收到视频通话邀请</p>
        <button @click="acceptCall" class="accept-button">接听</button>
        <button @click="hangUp" class="hangup-button">拒绝</button>
      </div>

      <div v-if="callStatus === 'in_call'" class="control-panel">
        <button @click="hangUp" class="hangup-button">结束通话</button>
      </div>
    </div>
  </div>
</template>

<script>
import { io } from "socket.io-client";
const serverUrl = 'https://172.20.10.10:5000';
// const serverUrl = 'https://192.168.1.2:5000';

export default {
  name: 'VideoCall',
  data() {
    return {
      socket: null,
      peerConnection: null,
      localStream: null,
      roomId: 'default_room',
      pendingCandidates: [], // 新增ICE候选缓存队列

      // 状态管理
      callStatus: 'idle', // 'idle'|'calling'|'ringing'|'in_call'

      // ICE配置
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        {
          urls: 'turn:numb.viagenie.ca',
          username: 'webrtc@live.com',
          credential: 'muazkh'
        }
      ]
    };
  },
  mounted() {
    this.initSocket();
    this.initVideoElements();
  },
  beforeUnmount() {
    this.cleanUp();
  },
  methods: {
    // 初始化Socket连接
    initSocket() {
      this.socket = io(serverUrl, {
        reconnectionAttempts: 5,
        reconnectionDelay: 1000,
      });

      // Socket事件监听
      this.socket.on('connect', () => {
        console.log('连接到信令服务器');
        this.socket.emit('joinRoom', this.roomId);
      });

      this.socket.on('callRemote', () => {
        if (this.callStatus === 'idle') this.callStatus = 'ringing';
      });

      this.socket.on('acceptCall', async () => {
        if (this.callStatus === 'calling') {
          await this.createPeerConnection(true);
        }
      });

      this.socket.on('sendOffer', async (offer) => {
        // if (this.callStatus === 'ringing') {
        //   await this.handleOffer(offer);
        // }
        if (this.callStatus === 'ringing' || this.callStatus === 'answered') {
          await this.handleOffer(offer);
        }
      });

      this.socket.on('sendAnswer', async (answer) => {
        if (this.callStatus === 'calling') {
          await this.handleAnswer(answer);
        }
      });

      // 修改后的ICE候选处理逻辑
      this.socket.on('sendCandidate', async (candidate) => {
        try {
          console.log('接收到ICE候选:', candidate);
          if (this.peerConnection && this.peerConnection.remoteDescription) {
            await this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
          } else {
            this.pendingCandidates.push(candidate); // 缓存候选
            console.log('缓存ICE候选:', candidate);
          }
        } catch (e) {
          console.error('添加ICE候选失败:', e);
        }
      });

      this.socket.on('hangUp', () => {
        this.cleanUp();
        this.callStatus = 'idle';
      });
    },

    // 初始化视频元素
    initVideoElements() {
      this.$refs.localVideo.srcObject = null;
      this.$refs.remoteVideo.srcObject = null;
    },

    // 获取本地媒体流
    async getLocalStream() {
      try {
        this.localStream = await navigator.mediaDevices.getUserMedia({
          audio: true,
          video: { width: { ideal: 1280 }, height: { ideal: 720 } }
        });
        this.$refs.localVideo.srcObject = this.localStream;
        return this.localStream;
      } catch (error) {
        console.error('获取媒体设备失败:', error);
        throw error;
      }
    },

    // 开始呼叫
    async startCall() {
      try {
        await this.getLocalStream();
        this.callStatus = 'calling';
        this.socket.emit('callRemote', this.roomId);
      } catch (error) {
        console.error('发起呼叫失败:', error);
        this.callStatus = 'idle';
      }
    },

    // 接听呼叫
    async acceptCall() {
      try {
        await this.getLocalStream();
        // -   await this.createPeerConnection(false);
        // -   this.callStatus = 'in_call';
        // -   this.socket.emit('acceptCall', this.roomId);
        // 只采集本地流并告诉对方“我已就绪”
        this.callStatus = 'answered';
        this.socket.emit('acceptCall', this.roomId);
      } catch (error) {
        console.error('接听失败:', error);
        this.hangUp();
      }
    },

    // 挂断通话
    hangUp() {
      this.socket.emit('hangUp', this.roomId);
      this.cleanUp();
      this.callStatus = 'idle';
    },

    // 创建RTCPeerConnection
    async createPeerConnection(isCaller) {
      this.peerConnection = new RTCPeerConnection({
        iceServers: this.iceServers,
        iceTransportPolicy: 'all',
        iceCandidatePoolSize: 0
      });

      // 添加本地流
      this.localStream.getTracks().forEach(track => {
        this.peerConnection.addTrack(track, this.localStream);
      });

      // ICE候选处理
      this.peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
          console.log('发送ICE候选:', event.candidate);
          this.socket.emit('sendCandidate', {
            roomId: this.roomId,
            candidate: event.candidate
          });
        }
      };

      // 远程流处理
      this.peerConnection.ontrack = (event) => {
        console.log("Remote stream received:", event.streams[0]); // 添加日志
        this.$refs.remoteVideo.srcObject = event.streams[0];
      };

      // ICE连接状态监控
      this.peerConnection.oniceconnectionstatechange = () => {
        console.log('ICE状态:', this.peerConnection.iceConnectionState);
        if (this.peerConnection.iceConnectionState === 'disconnected') {
          this.hangUp();
        }
      };

      // 创建Offer
      if (isCaller) {
        try {
          const offer = await this.peerConnection.createOffer();
          console.log('Offer SDP:', offer.sdp);  // 检查是否有媒体行
          await this.peerConnection.setLocalDescription(offer);
          this.socket.emit('sendOffer', { roomId: this.roomId, offer });
        } catch (error) {
          console.error('创建offer失败:', error);
          this.hangUp();
        }
      }
    },

    async handleOffer(offer) {
      try {
        // 1. 如果还没 getLocalStream，就先采集
        if (!this.localStream) {
          await this.getLocalStream();
        }
        // 2. 新建 PeerConnection 并添加本地轨道
        await this.createPeerConnection(false);
        // 3. 设置远端 SDP
        await this.peerConnection.setRemoteDescription(offer);
        // 4. 先把缓存的 ICE 候选都加了
        while (this.pendingCandidates.length) {
          const c = this.pendingCandidates.shift();
          await this.peerConnection.addIceCandidate(new RTCIceCandidate(c));
        }
        // 5. 生成 answer 并发送
        const answer = await this.peerConnection.createAnswer();
        await this.peerConnection.setLocalDescription(answer);
        this.socket.emit('sendAnswer', { roomId: this.roomId, answer });
        // 6. 进入通话状态
        this.callStatus = 'in_call';
      } catch (err) {
        console.error('处理 Offer 失败:', err);
        this.hangUp();
      }
    },


    // 处理Answer
    async handleAnswer(answer) {
      try {
        await this.peerConnection.setRemoteDescription(answer);

        // 处理缓存候选
        while (this.pendingCandidates.length > 0) {
          const candidate = this.pendingCandidates.shift();
          await this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
        }

        this.callStatus = 'in_call';
      } catch (error) {
        console.error('处理answer失败:', error);
        this.hangUp();
      }
    },

    // 清理资源
    cleanUp() {
      if (this.peerConnection) {
        this.peerConnection.close();
        this.peerConnection = null;
      }

      if (this.localStream) {
        this.localStream.getTracks().forEach(track => track.stop());
        this.localStream = null;
        this.$refs.localVideo.srcObject = null;
      }

      this.$refs.remoteVideo.srcObject = null;
      this.pendingCandidates = []; // 清空缓存队列
    }
  }
};
</script>

<style scoped>
.video-call-container {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f0f2f5;
}

.video-container {
  position: relative;
  width: 600px;
  height: 400px;
  background: #000;
  border-radius: 8px;
}

.video-element {
  width: 50%;
  height: 100%;
}

.video-element.local {
  position: absolute;
  top: 0; left: 0;
  width: 50%; height: 50%;
}
.video-element.remote {
  position: absolute;
  top: 0; right: 0;
  width: 50%; height: 50%;
}


.control-panel {
  position: absolute;
  bottom: 20px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 15px;
  color: white;
}

.call-button, .accept-button, .hangup-button {
  padding: 10px 20px;
  border: none;
  border-radius: 20px;
  font-size: 16px;
  cursor: pointer;
  transition: all 0.3s;
}

.call-button {
  background-color: #4CAF50;
  color: white;
}

.accept-button {
  background-color: #4CAF50;
  color: white;
}

.hangup-button {
  background-color: #f44336;
  color: white;
}

.call-button:hover, .accept-button:hover {
  background-color: #45a049;
}

.hangup-button:hover {
  background-color: #d32f2f;
}
</style>